package com.sailing.xjpb.web.base.swagger.configration;

import com.fasterxml.classmate.TypeResolver;
import com.sailing.xjpb.web.base.swagger.SwaggerPageable;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.domain.Pageable;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ParameterType;
import springfox.documentation.service.RequestParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.Collections;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;

/**
 * swagger-api配置说明
 *
 * @author yaowei
 * createDate: 2020-12-08
 */
@Slf4j
@Data
@Configuration
@ConfigurationProperties(prefix = "xjpb.web.swagger")
public class SwaggerConfig {

    /**
     * swagger访问host= ip:port
     */
    private String host;
    /**
     * swagger扫描包路径-通过扫描包路径生成swagger接口
     */
    private String basePackage;
    /**
     * 当前文档的标题
     */
    private String title;
    /**
     * 当前文档的详细描述
     */
    private String description;
    /**
     * 当前文档的版本
     */
    private String version;
    /**
     * 是否可用
     */
    private Boolean enable;

    @Bean
    public Docket createRestApi() {
        // Authorization
        RequestParameterBuilder ticketPar = new RequestParameterBuilder();
        ticketPar.name("Authorization").description("access token")
                .in(ParameterType.HEADER).required(false).build();
        List<RequestParameter> pars = Collections.singletonList(ticketPar.build());
        log.info("init swagger with host={},basePackage={}", host, basePackage);
        return new Docket(DocumentationType.SWAGGER_2).enable(enable).host(host).apiInfo(apiInfo()).select()
                .apis(RequestHandlerSelectors.basePackage(basePackage)).paths(PathSelectors.any()).build()
                .globalRequestParameters(pars);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title(title).description(description).version(version).build();
    }

    /**
     * 对spring data的pageable参数解析
     *
     * @param resolver 类型解析器
     */
    @Bean
    @ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
    public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
        return new AlternateTypeRuleConvention() {
            @Override
            public int getOrder() {
                return Ordered.HIGHEST_PRECEDENCE;
            }

            @Override
            public List<AlternateTypeRule> rules() {
                return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(SwaggerPageable.class)));
            }
        };
    }
}
